package com.fengyunhe.common.utils;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.shiro.codec.Base64;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * @author yangxun
 */
public class ImageUtil {

    /**
     * 生成缩略图
     *
     * @param srcImageFile     源图片文件的File实例 File file = new File("文件名");
     * @param dstImageFileName 待生成的缩略图片完整路径(生成的格式为：image/jpeg);
     * @throws Exception
     */
    public static void makeSmallImage(File srcImageFile, String dstImageFileName)
            throws Exception {
        FileOutputStream fileOutputStream = null;
        JPEGImageEncoder encoder = null;
        BufferedImage tagImage = null;
        Image srcImage = null;
        try {
            srcImage = ImageIO.read(srcImageFile);
            int srcWidth = srcImage.getWidth(null);// 原图片宽度
            int srcHeight = srcImage.getHeight(null);// 原图片高度
            int dstMaxSize = 120;// 目标缩略图的最大宽度/高度，宽度与高度将按比例缩写
            int dstWidth = srcWidth;// 缩略图宽度
            int dstHeight = srcHeight;// 缩略图高度
            float scale = 0;
            // 计算缩略图的宽和高
            if (srcWidth > dstMaxSize) {
                dstWidth = dstMaxSize;
                scale = (float) srcWidth / (float) dstMaxSize;
                dstHeight = Math.round((float) srcHeight / scale);
            }
            srcHeight = dstHeight;
            if (srcHeight > dstMaxSize) {
                dstHeight = dstMaxSize;
                scale = (float) srcHeight / (float) dstMaxSize;
                dstWidth = Math.round((float) dstWidth / scale);
            }
            // 生成缩略图
            tagImage = new BufferedImage(dstWidth, dstHeight,
                    BufferedImage.TYPE_INT_RGB);
            tagImage.getGraphics().drawImage(srcImage, 0, 0, dstWidth,
                    dstHeight, null);
            fileOutputStream = new FileOutputStream(dstImageFileName);
            encoder = JPEGCodec.createJPEGEncoder(fileOutputStream);
            encoder.encode(tagImage);
            fileOutputStream.close();
            fileOutputStream = null;
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (Exception e) {
                }
                fileOutputStream = null;
            }
            encoder = null;
            tagImage = null;
            srcImage = null;
            System.gc();
        }
    }

    /**
     * 生成正方形缩略图，将图片按照给定的最大高度或宽度，等比例缩小，取中间正方形部分进行裁切
     *
     * @param inputStream
     * @param output
     * @param size
     */
    public static void makeSquareImage(InputStream inputStream,
                                       OutputStream output, int size) throws Exception {
        JPEGImageEncoder encoder = null;
        BufferedImage tagImage = null;
        Image srcImage = null;
        try {
            srcImage = ImageIO.read(inputStream);
            int srcWidth = srcImage.getWidth(null);// 原图片宽度
            int srcHeight = srcImage.getHeight(null);// 原图片高度

            int dstWidth = srcWidth;// 缩略图宽度
            int dstHeight = srcHeight;// 缩略图高度
            float scale = 0;
            // 计算缩略图的宽和高
            if (srcWidth > size) {
                dstWidth = size;
                scale = (float) srcWidth / (float) size;
                dstHeight = Math.round((float) srcHeight / scale);
            }
            srcHeight = dstHeight;
            if (srcHeight > size) {
                dstHeight = size;
                scale = (float) srcHeight / (float) size;
                dstWidth = Math.round((float) dstWidth / scale);
            }
            // 生成缩略图
            tagImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
            tagImage.getGraphics().drawImage(srcImage, 0, 0, size, size, null);
            encoder = JPEGCodec.createJPEGEncoder(output);
            encoder.encode(tagImage);
            output.close();
            output = null;
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (Exception e) {
                }
                output = null;
            }
            encoder = null;
            tagImage = null;
            srcImage = null;
            System.gc();
        }
    }

    /**
     * 生成缩略图，将图片按照限制的最大高度或宽度等比例缩小
     *
     * @param inputStream 输入流
     * @param output      输出流
     * @param maxWidth    最大宽度
     * @param maxHeight   最大高度
     * @throws Exception
     */
    public static void makeSmallImage(InputStream inputStream,
                                      OutputStream output, int maxWidth, int maxHeight) throws Exception {
        JPEGImageEncoder encoder = null;
        BufferedImage tagImage = null;
        Image srcImage = null;
        try {
            srcImage = ImageIO.read(inputStream);
            int srcWidth = srcImage.getWidth(null);// 原图片宽度
            int srcHeight = srcImage.getHeight(null);// 原图片高度
            int dstWidth = srcWidth;// 缩略图宽度
            int dstHeight = srcHeight;// 缩略图高度
            float scale = 0;
            // 计算缩略图的宽和高
            if (srcWidth > maxWidth) {
                dstWidth = maxWidth;
                scale = (float) srcWidth / (float) maxWidth;
                dstHeight = Math.round((float) srcHeight / scale);
            }
            srcHeight = dstHeight;
            if (srcHeight > maxHeight) {
                dstHeight = maxHeight;
                scale = (float) srcHeight / (float) maxHeight;
                dstWidth = Math.round((float) dstWidth / scale);
            }
            // 生成缩略图
            tagImage = new BufferedImage(dstWidth, dstHeight,
                    BufferedImage.TYPE_INT_RGB);
            tagImage.getGraphics().drawImage(srcImage, 0, 0, dstWidth,
                    dstHeight, null);

            encoder = JPEGCodec.createJPEGEncoder(output);
            encoder.encode(tagImage);
            output.close();
            output = null;
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (Exception e) {
                }
                output = null;
            }
            encoder = null;
            tagImage = null;
            srcImage = null;
            System.gc();
        }
    }

    /**
     * 图片生成base64
     *
     * @param imgFilePath
     * @return
     */
    public static String getImageBase64Str(String imgFilePath) {// 将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        byte[] data = null;

        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(imgFilePath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 对字节数组Base64编码
        return Base64.decodeToString(data);// 返回Base64编码过的字节数组字符串
    }

    /**
     * base64 转图片
     *
     * @param imgStr
     * @param imgFilePath
     * @return
     */
    public static boolean generateImageByBase64(String imgStr,
                                                String imgFilePath) {// 对字节数组字符串进行Base64解码并生成图片
        if (imgStr == null) // 图像数据为空
            return false;

        try {
            // Base64解码
            byte[] bytes = Base64.decode(imgStr);
            for (int i = 0; i < bytes.length; ++i) {
                if (bytes[i] < 0) {// 调整异常数据
                    bytes[i] += 256;
                }
            }
            // 生成jpeg图片
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(bytes);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
